package fstools

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

func ScanFiles(loc string) (paths []string, isDirs []bool, err error) {

	fi, err := os.Stat(loc)
	if err != nil {
		return nil, nil, err
	}

	if fi.IsDir() {
		paths = append(paths, loc)
		isDirs = append(isDirs, true)

		entrys, err := os.ReadDir(loc)
		if err != nil {
			return nil, nil, err
		}

		for _, entry := range entrys {
			subPaths, subIsDirs, err := ScanFiles(filepath.Join(loc, entry.Name()))
			if err != nil {
				return nil, nil, err
			}

			paths = append(paths, subPaths...)
			isDirs = append(isDirs, subIsDirs...)
		}

	} else {
		paths = append(paths, loc)
		isDirs = append(isDirs, false)
	}

	return
}

// 复制 me 至 /a/b/d 目录下：
// src: /a/b/c/me
// dstDir: /a/b/d
func CopyTo(src, dstDir string) error {
	parent := filepath.Dir(src)
	dstDir = filepath.Clean(dstDir)

	srcPaths, isDirs, err := ScanFiles(src)
	if err != nil {
		return err
	}

	var dstPaths []string

	for i := 0; i < len(srcPaths); i++ {
		cleanDst := strings.ReplaceAll(filepath.Clean(srcPaths[i]), parent, "")
		cleanDst = strings.Replace(cleanDst, "\\", "", 1)
		dst := filepath.Join(dstDir, cleanDst)

		if isDirs[i] {
			dstPaths = append(dstPaths, "")
			if e := os.MkdirAll(dst, os.ModeDir); e != nil {
				return e
			}
		} else {
			dstPaths = append(dstPaths, dst)
		}
	}

	for i := 0; i < len(srcPaths); i++ {

		src := srcPaths[i]
		dst := dstPaths[i]
		if dst == "" {
			continue
		}

		srcF, openErr := os.Open(src)
		if openErr != nil {
			return openErr
		}
		defer srcF.Close()

		dstF, crateErr := os.Create(dst)
		if crateErr != nil {
			err = crateErr
			return crateErr
		}
		defer dstF.Close()

		n, copyErr := io.Copy(dstF, srcF)
		if copyErr != nil {
			if !os.IsExist(copyErr) {
				return fmt.Errorf("copy %s to %s at %d: %w", src, dstDir, n, copyErr)
			}
			return copyErr
		}
	}

	return nil
}
